#pragma once
#include <string>
#include "Dispatcher.hpp"
#include "EventLoop.hpp"
#include "Channel.hpp"
#include <sys/epoll.h>
using namespace std;

class EpollDispatcher : public Dispatcher
{
public:
    // 初始化epoll,select,poll函数对应的数据块
    EpollDispatcher(class EventLoop *evloop)
    :Dispatcher(evloop)
    {
        m_epfd = epoll_create(10);
        if (m_epfd == -1)
        {
            perror("epoll_create");
            exit(0);
        }
        m_events = new struct epoll_event[_maxNode];
        m_name = "Epoll";
    }
    ~EpollDispatcher() // 实现多态需要将析构函数设置为虚函数将下面的函数设置为虚函数后，子类就能对父类函数进行重写操作
    {
        close(m_epfd);
        delete[] m_events;
    }

    // 添加   表示该函数是从父类继承的虚函数
    int add() override
    {
        int ret = epollCtl(EPOLL_CTL_ADD);
        if (ret == -1)
        {
            perror("epollCtl add");
            exit(0);
        }
        return ret;
    }
    // 删除
    int remove() override
    {
        int ret = epollCtl(EPOLL_CTL_DEL);
        if (ret == -1)
        {
            perror("epollCtl delete");
            exit(0);
        }
        m_channel->destoryCallback(const_cast<void *>(m_channel->getArg()));
        return ret;
    }
    // 修改
    int modify() override
    {
        int ret=epollCtl(EPOLL_CTL_MOD);
        if(ret == -1)
        {
            perror("epollCtl modify");
            exit(0);
        }
        return ret;
    }
    // 事件检测
    int dispatch(int timeout = 2) override
    {
        int count = epoll_wait(m_epfd,m_events,_maxNode,timeout *1000);
    for(int i =0;i<count;++i)
    {
        //依次取出有效数组的文件描述符并保存
        int events=m_events[i].events;
        int fd =m_events[i].data.fd;
        if(events &EPOLLERR || events&EPOLLHUP)
        {
            //对方断开连接，删除fd
            //epollRemove(Channel,evLoop);
            continue;
        }
        if(events & EPOLLIN)
        {
            m_evLoop->eventActivate(fd,(int)FDEvent::ReadEvent);
        }
        if(events & EPOLLOUT)
        {
            m_evLoop->eventActivate(fd,(int)FDEvent::WriteEvent);
        }
    }
    return 0;
    }

private:
    int m_epfd;
    struct epoll_event *m_events;
    const int _maxNode = 520;

    int epollCtl(int op);
};